#!/bin/bash
CUR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
GH_PROXY=${URL_githubProxy:-https://ghproxy.com/}
IMAGE_PROXY="${URL_imageProxy:+$URL_imageProxy/}"


MANIFESTS=(
  ${GH_PROXY}${URL_ingressNginx_manifest_0:-"https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v\${TARGET_VERSION}/deploy/static/provider/cloud/deploy.yaml"}
)
CHART=${GH_PROXY}${URL_ingressNginx_chart:-"https://github.com/kubernetes/ingress-nginx/releases/download/helm-chart-\${CHART_VERSION}/ingress-nginx-\${CHART_VERSION}.tgz"}
#二进制包下载路径
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')

DOWNLOAD_DIR=$CUR_DIR/package
DEFAULT_VERSION=${LATEST_VERSION:-1.8.2}

# 检查是否有curl和wget
HAS_CURL="$(command -v curl >/dev/null 2>&1 && echo true || echo false)"
HAS_WGET="$(command -v wget >/dev/null 2>&1 && echo true || echo false)"
bash_xc="bash -xc"
if ! $HAS_CURL && ! $HAS_WGET; then
  echo "Either curl or wget is required"
  exit 1
fi

##include scripts##
##include end##


#usage: download_url <url> [target] 
download_url() {
  local target
  local url=$1
  local remote_file=""
  
  if [ $# -eq 2 ]; then
    target=$2
  elif [ $# -eq 1 ]; then 
    target=${1##*/}
  else
    echo "cmd err, usage: download_url <url> [target]"
    return 1
  fi
  if [ ! -f "$target" ] || ${FORCE} ; then
    if $HAS_CURL; then
      $bash_xc "curl -fsSL $url -o $target"
      if [ $? -ne 0 ]; then
        echo "curl or wget failed"
        return 3
      fi
    elif $HAS_WGET; then
      $bash_xc "wget -q $url -O $target"
      if [ $? -ne 0 ]; then
        echo "curl or wget failed"
        return 3
      fi
    fi
    echo "get $(basename $target) successfully"
    return 0
  else
    echo "do not get $(basename $url): file exist or force=${FORCE} "
    return 0
  fi
  return 0
}

download_url_until_succeed() {
  local target
  local url=$1
  
  if [ $# -eq 2 ]; then
    target=$2
  elif [ $# -eq 1 ]; then 
    target=${1##*/}
  else
    echo "cmd err, usage: download_url <url> [target]"
    return 1
  fi
  echo "download $url $target"
  
  while ! download_url $url $target; do
    sleep 5
  done
}


#set -x
# Define functions to check version and install Kubernetes components

# check if the current version is less than the target version.
# 检查当前版本是否小于目标版本。
check_version_lt() {
    test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"
}

# check if the current version is greater than or equal to the target version.
# 检查当前版本是否大于或等于目标版本。
check_version_ge() {
    test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"
}

get_default_version() {
    if $ONLINE; then
        helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx > /dev/null
        #CHART_VERSION=$(helm search repo ingress-nginx -o yaml  | grep "^  version:" | awk -F ": " '{print $2}')
        DEFAULT_VERSION=$(helm search repo ingress-nginx -o yaml  | grep app_version: | awk -F ": " '{print $2}')
        echo "$DEFAULT_VERSION"
    else
        #helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
        #CHART_VERSION=$(helm search repo ingress-nginx -o yaml  | grep "^  version:" | awk -F ": " '{print $2}')
        #APP_VERSION=$(helm search repo ingress-nginx -o yaml  | grep app_version: | awk -F ": " '{print $2}')
        CHART_VERSION=${DEFAULT_CHART_VERSION}
        echo "$DEFAULT_VERSION"
    fi
}

app_version_to_chart_version() {
    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx > /dev/null
    helm search repo ingress-nginx -l | grep "$1" | awk '{print $2}'
}

# deletes the old version of Kubernetes components.
# 删除旧版本的 Kubernetes 组件。
delete_old_version() {
	yamls=$(ls $CUR_DIR/manifest/{*.yaml,*.yml} 2>/dev/null)
	for i in $yamls; do
		bash -xc "kubectl delete -f $i > /dev/null 2>&1"
	done

	bash -xc "helm uninstall ingress-nginx --namespace ingress-nginx > /dev/null 2>&1"

}

waiting_for_kubernetes() {
  kubeApiServer=$(kubectl cluster-info | grep "Kubernetes control plane" | grep -oE "http.*://.*:[0-9]*")
  if [ -z "$kubeApiServer" ]; then
      echo "kubernetes not installed, exit\n"
      exit
  fi
  echo -en "waiting for kubernetes to be ready  "
  while true; do
    if [ "$(curl -k --silent --max-time 3 ${kubeApiServer}/healthz)" == "ok" ] ; then
	  echo -en " ok\n"
      break
    else
	  echo -en "."
      sleep 3
    fi
  done
}
install_ingress_nginx() {
    download_pkg
    set -x
	waiting_for_kubernetes
	if [ $DEPLOY_MODE == "manifest" ]; then
	    yamls=$(ls $CUR_DIR/manifest/{*.yaml,*.yml} 2>/dev/null)
		for i in $yamls; do
		    kubectl apply -f $i
		done
	elif [ $DEPLOY_MODE == "chart" ]; then
	    if [ -f $CUR_DIR/chart/${CHART##*/} ]; then
		    kubectl create namespace ingress-nginx
		    helm upgrade --install ingress-nginx $CUR_DIR/chart/${CHART##*/} --namespace ingress-nginx  -f $CUR_DIR/chart/values.yaml
		fi
	fi
    set +x
}
download_pkg() {
    bash -xc "mkdir -p $CUR_DIR/{manifest,chart}"
    MANIFESTS=$(eval echo ${MANIFESTS})
    CHART=$(eval echo ${CHART})

	for i in ${MANIFESTS[@]}; do
		local yaml=$(eval echo ${i})
		local ext=${yaml##*.}
		local filename=$(basename ${yaml##*/} .$ext)-${TARGET_VERSION}.yaml
		if [ ! -f $CUR_DIR/manifest/$filename ]; then
			download_url_until_succeed ${yaml} $CUR_DIR/manifest/$filename
			sed -i "s|registry.k8s.io|${IMAGE_PROXY}registry.k8s.io|g" $CUR_DIR/manifest/$filename
		fi
	done
	
    if [ ! -f $CUR_DIR/chart/${CHART##*/} ]; then
        download_url_until_succeed ${CHART} $CUR_DIR/chart/${CHART##*/}
    fi
	#cp -rf $CUR_DIR/chart/${CHART##*/} $DOWNLOAD_DIR/chart/
	if [ ! -f $CUR_DIR/chart/values.yaml ] ; then
	     helm show values  $CUR_DIR/chart/${CHART##*/} > $CUR_DIR/chart/values.yaml
		 sed -i "s|registry.k8s.io|${IMAGE_PROXY}registry.k8s.io|g" $CUR_DIR/chart/values.yaml
	fi
	#cp -rf $CUR_DIR/chart/values.yaml $DOWNLOAD_DIR/chart/
}


clean_download() {
    rm -rf $CUR_DIR/chart
    rm -rf $CUR_DIR/manifest
}
function print_usage() {
    echo "Usage: $0 [--force|-f] [--version=<version>] [--rm|--remove] [--clean|-c] [--downloadonly|-d][--deployMode=<manifest|chart>]"
    echo "Options:"
    echo "  --force|-f: force installation, default force=false"
    echo "  --version=<version>: specify the version to be installed, default is latest(online) or 1.8.2(apt/yum)"
    echo "  --rm|--remove: uninstall Kubernetes"
    echo "  --clean|-c: remove downloaded files"
    echo "  --downloadonly|-d: only download kubernetes package, do not install"
	echo "  --deployMode=[manifest|chart]: manifest: kubectl apply -f x.yaml, chart: helm install"
    echo "  example1, download 1.8.2 "
    echo "          ./install.sh --version=1.8.2 --force --downloadonly"
    echo "  example2, install 1.8.2" 
    echo "         ./install.sh --version=1.8.2"
    echo "  example3, install 1.8.2 using online method(by apt or yum), and force installation:" 
    echo "         ./install.sh --version=1.8.2  -fo"
}

#
#=====================main func ==============================
if [[ $EUID -ne 0 ]]; then
    echo "This script must be run as root"
    exit 1
fi

#清除旧版本的影响，保证command -v命令得到正确的结果
hash -r

ARGS=$#

# Parse command line arguments
while [[ $# -gt 0 ]]
do
    key="$1"
    case $key in
    --clean|-c)
        if [[ $ARGS -eq 1 ]]; then
            clean_download
            exit 0
        fi
        AUTOCLEAN=true
        shift
        ;;
    --downloadonly|-d)
        DOWNLOAD_ONLY=true
        shift
        ;;
    --force|-f)
        FORCE=true
        shift
        ;;
    --version)
        shift
        TARGET_VERSION="${key}"
        shift
        ;;
    --version=*)
        TARGET_VERSION="${key#*=}"
        shift
        ;;
	--deployMode)
        shift
        DEPLOY_MODE="${key}"
        shift
        ;;
    --deployMode=*)
        DEPLOY_MODE="${key#*=}"
        shift
        ;; 	
    --help)
        print_usage
        exit 1
        ;;
    --rm|--remove)
        echo "Kubernetes components uninstall..."
        delete_old_version
        exit 1
        ;;
    -[^-]*)
        for ((i=1; i<${#key}; i++)); do
          case "${key:$i:1}" in
            f) FORCE=true ;;
            c) AUTOCLEAN=true ;;
            d) DOWNLOAD_ONLY=true ;;
            *) print_usage; exit 1 ;;
          esac
        done
        shift    
        ;;
    *)    # unknown option
        print_usage
        exit 1
        ;;
    esac
done

FORCE=${FORCE:-false}
DOWNLOAD_ONLY=${DOWNLOAD_ONLY:-false}
AUTOCLEAN=${AUTOCLEAN:-false}

#设置软件安装源，从而获得最新版本
TARGET_VERSION=${TARGET_VERSION:-$(get_default_version)}
CHART_VERSION=$(app_version_to_chart_version $TARGET_VERSION)
DEPLOY_MODE=${DEPLOY_MODE:-chart}

echo "--version=$TARGET_VERSION --force=$FORCE --downloadonly=$DOWNLOAD_ONLY --clean=$AUTOCLEAN --deployMode=$DEPLOY_MODE"

if $DOWNLOAD_ONLY ; then
    download_pkg
    exit 0
fi
# Main script
echo "Install version $TARGET_VERSION ..."
install_ingress_nginx
$AUTOCLEAN && clean_download


